package top.ieei.demo.tftp;

/**
 * 
 * TFTP出错响应包<br>
 * @author xiecongshu
 */
public class TftpError extends TftpPacket
{
    /**
     * 错误码位置索引：2
     */
    protected static final int INDEX_ERRCODE = 2;
    
    /**
     * 错误信息起始位置索引：4
     */
    protected static final int INDEX_ERRORMSG = 4;
    
    /**
     * 没有错误
     */
    public final static int ERROR_NO_ERROR = -1;
    
    /**
     * 未定义错误
     */
    public final static int ERROR_NOT_DEFINED = 0;
    
    /**
     * 文件未找到错误
     */
    public final static int ERROR_FILE_NOT_FOUND = 1;
    
    /**
     * 访问冲突
     */
    public final static int ERROR_ACCESS_VIOLATION = 2;
    
    /**
     * 磁盘已满，或超过分配值
     */
    public final static int ERROR_DISK_FULL = 3;
    
    /**
     * 非法操作
     */
    public final static int ERROR_ILLEGAL_OP = 4;
    
    /**
     * 未知的传输ID
     */
    public final static int ERROR_UNKNOWN_TRANS_ID = 5;
    
    /**
     * 文件已经存在
     */
    public final static int ERROR_FILE_EXISTS = 6;
    
    /**
     * 没有该用户
     */
    public final static int ERROR_NO_SUCH_USER = 7;
    
    /**
     * 最小数据包大小
     */
    public static final int MIN_PACKET_SIZE = 5;
    
    /**
     * 操作码，出错标记：5
     */
    public static final int OPCODE = 5;
    
    /**
     * 错误信息集
     */
    public static final String[] ERRORS = {"Unknown error", "File not found",
            "Access violation", "Disk full or allocation exceeded",
            "Illegal TFTP operation", "Unknown transfer ID",
            "File already exists", "No such user"};
    
    /**
     * 错误码
     */
    private int errorCode = ERROR_NO_ERROR;
    
    /**
     * 错误信息
     */
    private String errorMessage = "";
    
    /**
     * 
     * 构造函数<br>
     * 
     * @param code
     * @param message
     * @throws TftpException
     */
    public TftpError(int code, String message) throws TftpException
    {
        super();
        errorCode = code;
        errorMessage = message;
    }
    
    /**
     * 通过UDP数据构建TFTP响应
     * <默认构造函数>
     * @param tftpBytes
     */
    public TftpError(byte[] tftpBytes) throws TftpException
    {
        super(tftpBytes);
        
        errorCode = byteToInt(tftpBytes[INDEX_ERRCODE],
                tftpBytes[INDEX_ERRCODE + 1]);
        
        if (INDEX_ERRORMSG >= tftpBytes.length)
        {
            throw new TftpException(
                    "Argument passed to constructor is not a complete "
                            + getClass().getName() + " packet!");
        }
        
        try
        {
            StringBuffer sb = new StringBuffer();
            for (int i = INDEX_ERRORMSG; i < tftpBytes.length; i++)
            {
                if (tftpBytes[i] == 0)
                {
                    break;
                }
                
                sb.append((char) tftpBytes[i]);
            }
            errorMessage = sb.toString();
        }
        catch (Exception e)
        {
            throw new TftpException(e);
        }
    }
    
    /**
     *  获取响应数据的字节数组<br>
     * @return byte[]
     */
    public byte[] getBytes()
    {
        int tftpLen = MIN_PACKET_SIZE + errorMessage.length() + 1;
        byte[] tftpBytes = new byte[tftpLen];
        
        // 加入两字节的操作码
        tftpBytes[INDEX_OPCODE] = (byte) ((OPCODE >> 8) & 0xff);
        tftpBytes[INDEX_OPCODE + 1] = (byte) (OPCODE & 0xff);
        
        // 加入两字节的错误码
        tftpBytes[INDEX_ERRCODE] = (byte) ((errorCode >> 8) & 0xff);
        tftpBytes[INDEX_ERRCODE + 1] = (byte) (errorCode & 0xff);
        
        // 加入错误信息
        System.arraycopy(errorMessage.getBytes(),
                0,
                tftpBytes,
                INDEX_ERRORMSG,
                errorMessage.length());
        
        // 加入 0表示结束
        tftpBytes[tftpLen - 1] = 0;
        return tftpBytes;
    }
    
    /**
     * 获取错误码
     * @return int
     * @see [类、类#方法、类#成员]
     */
    public int getErrorCode()
    {
        return errorCode;
    }
    
    /**
     * 获取错误信息
     * @return String
     */
    public String getErrorMessage()
    {
        return errorMessage;
    }
    
    /**
     * 根据错误信息id获取错误信息
     * @param msgId
     * @return String
     */
    public static String getErrorMessage(int msgId)
    {
        if (msgId > ERROR_NOT_DEFINED && msgId <= ERROR_NO_SUCH_USER)
        {
            return ERRORS[msgId];
        }
        else
        {
            return ERRORS[ERROR_NOT_DEFINED];
        }
    }
    
    /**
     * 获取操作码
     * @return int
     */
    public int getOpCode()
    {
        return OPCODE;
    }
    
    /**
     * 获取最小包大小
     * @return int
     */
    public int getMinPacketSize()
    {
        return MIN_PACKET_SIZE;
    }
}
